#ifdef _WIN64
# ifdef _M_IA64
#  define _win_ "win-ia64"
# else
#  define _win_ "win-x64"
# endif
#else
# define _win_ "win-x86"
#endif

#define VERS "0.5"

static const char *alt_name = 0;

static bool out( const char *str, bool err = false );

static void usage()
{
   out("=(W17)=  uname");
   if (alt_name) { out("-");  out(alt_name); }
   out("  " _win_ " version " VERS "\r\n\r\nUsage:\r\n  ");
   out(alt_name ? alt_name : "uname");
   out(".exe [-");
   if (!alt_name) out("srvmipnoaXcuM");
   out("h]\r\n");
}

static const char alt_names[] = "arch\0hostname\0logname\0user\0whoami\0";

//=======================================================================================

#define  STRICT   1
#define  NOMINMAX 1
#define  WIN32_LEAN_AND_MEAN

#if defined(_WIN32) && !defined(WIN32)
# define WIN32
#endif

#if defined(_UNICODE) && !defined(UNICODE)
# define UNICODE
#endif
#if defined(UNICODE) && !defined(_UNICODE)
# define _UNICODE
#endif

#undef  _WIN32_WINNT
#define _WIN32_WINNT 0x601

#if _MSC_VER <= 1200
# pragma warning( disable : 4514 ) /* unreferenced inline function removed */
# pragma warning( disable : 4710 ) /* function not inlined */
# pragma warning( disable : 4711 ) /* function inlined */
# pragma warning( push )
# pragma warning( disable : 4305 )
#endif

#include <windows.h>
#include <tchar.h>

#if _MSC_VER <= 1200
# pragma warning( pop )
#endif

#ifndef VER_SUITE_WH_SERVER
#define VER_SUITE_WH_SERVER                         0x00008000
#endif

#ifndef PRODUCT_UNDEFINED
#define PRODUCT_UNDEFINED                           0x00000000
#define PRODUCT_ULTIMATE                            0x00000001
#define PRODUCT_HOME_BASIC                          0x00000002
#define PRODUCT_HOME_PREMIUM                        0x00000003
#define PRODUCT_ENTERPRISE                          0x00000004
#define PRODUCT_HOME_BASIC_N                        0x00000005
#define PRODUCT_BUSINESS                            0x00000006
#define PRODUCT_STANDARD_SERVER                     0x00000007
#define PRODUCT_DATACENTER_SERVER                   0x00000008
#define PRODUCT_SMALLBUSINESS_SERVER                0x00000009
#define PRODUCT_ENTERPRISE_SERVER                   0x0000000A
#define PRODUCT_STARTER                             0x0000000B
#define PRODUCT_DATACENTER_SERVER_CORE              0x0000000C
#define PRODUCT_STANDARD_SERVER_CORE                0x0000000D
#define PRODUCT_ENTERPRISE_SERVER_CORE              0x0000000E
#define PRODUCT_ENTERPRISE_SERVER_IA64              0x0000000F
#define PRODUCT_BUSINESS_N                          0x00000010
#define PRODUCT_WEB_SERVER                          0x00000011
#define PRODUCT_CLUSTER_SERVER                      0x00000012
#define PRODUCT_HOME_SERVER                         0x00000013
#define PRODUCT_STORAGE_EXPRESS_SERVER              0x00000014
#define PRODUCT_STORAGE_STANDARD_SERVER             0x00000015
#define PRODUCT_STORAGE_WORKGROUP_SERVER            0x00000016
#define PRODUCT_STORAGE_ENTERPRISE_SERVER           0x00000017
#define PRODUCT_SERVER_FOR_SMALLBUSINESS            0x00000018
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM        0x00000019
#define PRODUCT_HOME_PREMIUM_N                      0x0000001A
#define PRODUCT_ENTERPRISE_N                        0x0000001B
#define PRODUCT_ULTIMATE_N                          0x0000001C
#define PRODUCT_WEB_SERVER_CORE                     0x0000001D
#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT    0x0000001E
#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY      0x0000001F
#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING     0x00000020
#define PRODUCT_SERVER_FOUNDATION                   0x00000021
#define PRODUCT_HOME_PREMIUM_SERVER                 0x00000022
#define PRODUCT_SERVER_FOR_SMALLBUSINESS_V          0x00000023
#define PRODUCT_STANDARD_SERVER_V                   0x00000024
#define PRODUCT_DATACENTER_SERVER_V                 0x00000025
#define PRODUCT_ENTERPRISE_SERVER_V                 0x00000026
#define PRODUCT_DATACENTER_SERVER_CORE_V            0x00000027
#define PRODUCT_STANDARD_SERVER_CORE_V              0x00000028
#define PRODUCT_ENTERPRISE_SERVER_CORE_V            0x00000029
#define PRODUCT_HYPERV                              0x0000002A
#define PRODUCT_STORAGE_EXPRESS_SERVER_CORE         0x0000002B
#define PRODUCT_STORAGE_STANDARD_SERVER_CORE        0x0000002C
#define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE       0x0000002D
#define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE      0x0000002E
#define PRODUCT_STARTER_N                           0x0000002F
#define PRODUCT_PROFESSIONAL                        0x00000030
#define PRODUCT_PROFESSIONAL_N                      0x00000031
#define PRODUCT_SB_SOLUTION_SERVER                  0x00000032
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS             0x00000033
#define PRODUCT_STANDARD_SERVER_SOLUTIONS           0x00000034
#define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE      0x00000035
#define PRODUCT_SB_SOLUTION_SERVER_EM               0x00000036
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM          0x00000037
#define PRODUCT_SOLUTION_EMBEDDEDSERVER             0x00000038
#define PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE        0x00000039
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE   0x0000003F
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT       0x0000003B
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL       0x0000003C
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC    0x0000003D
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC    0x0000003E
#define PRODUCT_CLUSTER_SERVER_V                    0x00000040
#define PRODUCT_EMBEDDED                            0x00000041
#define PRODUCT_STARTER_E                           0x00000042
#define PRODUCT_HOME_BASIC_E                        0x00000043
#define PRODUCT_HOME_PREMIUM_E                      0x00000044
#define PRODUCT_PROFESSIONAL_E                      0x00000045
#define PRODUCT_ENTERPRISE_E                        0x00000046
#define PRODUCT_ULTIMATE_E                          0x00000047
#endif

//=======================================================================================

enum EOpts
{ e_s = 0x0001, e_r = 0x0002, e_v = 0x0004, e_m = 0x0008
, e_i = 0x0010, e_p = 0x0020,               e_n = 0x0080
, e_o = 0x0100, e_u = 0x0200, e_a = 0x0400, e_X = 0x0800
, e_c = 0x1000, e_M = 0x2000
};

//=======================================================================================

static char *dw2a( DWORD dw, char *ss )
{
   wsprintfA(ss, "%u", dw);
   return ss;
}

static bool out( const char *str, bool err )
{
   HANDLE h = ::GetStdHandle(err ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
   if ( INVALID_HANDLE_VALUE == h )
      return false;

   DWORD len = (DWORD)::lstrlenA(str);
   if ( !len )
      return true;

   DWORD dw = 0;
   if ( !::WriteFile(h, str, len, &dw, NULL) )
      return false;

   return dw == len;
}

static void out(const char *title, const char *text)
{
   bool silent = (*title <= ' ');
   out(title);
   if (!silent) out(": ");
   out(text);
   if (!silent) out("\r\n");
}

static void out(const char *title, DWORD val, const char *tail=0)
{
   bool silent = (*title <= ' ');
   char n[20];
   out(title);
   if (!silent) out(": ");
   out(dw2a(val,n));
   if (!silent && NULL != tail) out(tail);
   if (!silent) out("\r\n");
}

//---------------------------------------------------------------------------------------

static FARPROC get_func(const char *func)
{
   HMODULE h = ::GetModuleHandleA("kernel32");
   return (NULL == h) ? NULL : ::GetProcAddress(h, func);
}

static DWORD q2mb(unsigned __int64 sz)
{
#if defined(_WIN64) || defined(_DEBUG) || !defined(_M_IX86)
   DWORD mb = (DWORD)(sz >> 20);
#else
   union {
      unsigned __int64 qw;
      struct { DWORD lo; DWORD hi; } dw;
   } u;
   u.qw = sz;
   DWORD mb = (u.dw.lo >> 20) + (u.dw.hi << (32-20));
#endif
   return mb;
}

static DWORD memory_size_mb()
{
   DWORD msize;

   MEMORYSTATUS ms;
   ::GlobalMemoryStatus(&ms);
   msize = q2mb(ms.dwTotalPhys);

#ifndef _WIN64
   union {
      FARPROC f;
      BOOL (WINAPI *GlobalMemoryStatusEx)( __out LPMEMORYSTATUSEX lpBuffer );
   } u;
   MEMORYSTATUSEX ems;
   if (NULL != (u.f = get_func("GlobalMemoryStatusEx"))) {
      ems.dwLength = sizeof(ems);
      u.GlobalMemoryStatusEx(&ems);
      msize = q2mb(ems.ullTotalPhys);
   }
#endif

   DWORD round = msize < 512 ? 7 : 63;
   msize = (msize + round) & ~round;
   return msize;
}

//---------------------------------------------------------------------------------------

static void add_sp(char *os, const char *sp)
{
   while (*sp && (*sp & 255) <= ' ') ++sp;
   if (*sp) {
      os += ::lstrlenA(os);
      os[0] = ',', os[1] = ' ';
      ::lstrcpyA(os+2, sp);
      os += ::lstrlenA(os) - 1;
      while (*os == ' ') *os-- = '\0';
   }
}

//---------------------------------------------------------------------------------------

static bool get_hostname(char *buff, size_t nb)
{
   ::lstrcpyA(buff, "unknown");
   DWORD dw = (DWORD)nb - 1;
   BOOL res = ::GetComputerNameA(buff, &dw);
   return res != 0;
}

//---------------------------------------------------------------------------------------

static bool get_username(char *buff, size_t nb)
{
   ::lstrcpyA(buff, "unknown");
   DWORD dw = (DWORD)nb - 1;
   return ::GetUserNameA(buff, &dw) != 0;
}


//=======================================================================================

static void next_and_check_name( WCHAR* &p, WCHAR* &pname )
{
   WCHAR prev = *p++;
   if (prev == L'"' || prev == L':' || prev == L'\\' || prev == L'/')
      pname = p;
}

//---------------------------------------------------------------------------------------

int __stdcall Main (void)
{
   char kernel[16];
   char release[32];
   char version[128];
   char os[256];
   char host[256];
   char user[256];
   char machine[16];
   char processor[256];

   ::lstrcpyA(kernel, "WindowsNT");
   ::lstrcpyA(os, "Microsoft Windows ");
   ::lstrcpyA(machine, "unknown");

   
   int opts = 0, jj;
   const char *ps1 = NULL, *ps2 = NULL, *pa;

   WCHAR *params = ::GetCommandLineW(), *pname = NULL;
   if ( !params )
      return +11;

   if (*params == L'"') {
      ++params; while (*params != L'"' && *params) next_and_check_name(params, pname);
   }
   else {
      while (*params && *params > L' ') next_and_check_name(params,pname);
   }
   while (*params && (*params <= L' ' || *params == L'"')) ++params;
   if (*params && *params != L'-' && *params != L'/') {
      pname = params;
      while (*params && *params > L' ') ++params;
   }
   if (pname) {
      for (pa = alt_names; *pa; pa += ::lstrlenA(pa) + 1) {
         for (jj = 0; pa[jj]; ++jj) {
            int cw = (int)pname[jj]; if (cw >= L'A' && cw <= L'Z') cw -= L'A' - L'a';
            if (pa[jj] - 'a' != cw - L'a') break;
         }
         if (!pa[jj]) {
            alt_name = pa; break;
         }
      }
   }
   if (alt_name) {
      switch (alt_name[0]) {
         case 'w': case 'l': case 'u': opts = e_u; break;
         case 'h':                     opts = e_n; break;
         case 'a':                     opts = e_m; break;
      }
   }

   while (*params) {
      switch (*params) {
         case L's': opts |= e_s; break; // (s)ystem
         case L'r': opts |= e_r; break; // (r)elease
         case L'v': opts |= e_v; break; // (v)ersion
         case L'm': opts |= e_m; break; // (m)achine
         case L'i': opts |= e_i; break; // === -m
         case L'p': opts |= e_p; break; // (p)rocessor
         case L'n': opts |= e_n; break; // (n)ode == hostname
         case L'o': opts |= e_o; break; // (o)s
         case L'u': opts |= e_u; break; // (u)ser (my extension)
         case L'a': opts |= e_a; break; // (a)ll almost same as eXtended
         case L'X': opts |= e_X; break; // e(X)tended -- show all in multi-line mode
         case L'c': opts |= e_c; break; // (c)pu (my extension)
         case L'M': opts |= e_M; break; // (M)emory MB (my extension)
         case L'h': case L'?':
            usage();
         return 0;
         default:
            if (*params > L' ' && *params != L'"' && *params != L'-' && *params != L'/') {
               usage(); return +12;
            }
         break;
      }
      ++params;
   }
   if (!opts) opts = e_s;

   SYSTEM_INFO si;
   union {
      FARPROC f;
      VOID (WINAPI *GetNativeSystemInfo)(LPSYSTEM_INFO);
      BOOL (WINAPI *GetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
   } u;
   if (NULL != (u.f = get_func("GetNativeSystemInfo"))) u.GetNativeSystemInfo(&si);
   else ::GetSystemInfo(&si);
   
   OSVERSIONINFOEXA oi;
   bool ex = true;
   oi.dwOSVersionInfoSize = (DWORD)sizeof(OSVERSIONINFOEXA);
   if ( !::GetVersionExA((LPOSVERSIONINFOA)&oi) ) {
      ex = false;
      oi.dwOSVersionInfoSize = (DWORD)sizeof(OSVERSIONINFOA);
      if ( !::GetVersionExA((LPOSVERSIONINFOA)&oi) ) {
         out("GetVersionEx failed", true);
         return +13;
      }
   }

   get_hostname(host, sizeof(host));
   get_username(user, sizeof(user));
   
   if (oi.dwPlatformId < VER_PLATFORM_WIN32_NT) {
      oi.dwBuildNumber = (DWORD)LOWORD(oi.dwBuildNumber);
      ::lstrcpyA(kernel+7, "9x");

      if (oi.dwMinorVersion == 0) {
         ::lstrcpyA(os+18, "95");
         if (oi.dwBuildNumber >= 1111) {
            ::lstrcatA(os, ", OSR2");
            if (oi.dwBuildNumber >= 1212) ::lstrcatA(os, ".5");
         }
      }
      else if (oi.dwMinorVersion == 0x90) {
         ::lstrcpyA(os+18, "Me");
      }
      else {
         ::lstrcpyA(os+18, "98");
         if (oi.dwBuildNumber >= 2222) ::lstrcatA(os, ", Second Edition");
      }
   }
   else {
      if (oi.dwMajorVersion <= 4) {
         ps2 = "";
         if (oi.dwMajorVersion >= 4) {
            switch (oi.wProductType) {
               case VER_NT_WORKSTATION:       ps2 = ", Workstation";       break;
               case VER_NT_DOMAIN_CONTROLLER: ps2 = ", Domain Controller"; break;
               case VER_NT_SERVER:            ps2 = ", Server";            break;
            }
         }
         ::wsprintfA(os+18, "NT %u.%u%s", oi.dwMajorVersion, oi.dwMinorVersion, ps2);
      }
      else {
         switch (256*oi.dwMajorVersion + oi.dwMinorVersion) {
            case 0x500:
               ps1 = "2000";
               ps2 = "Server";
               if      (oi.wProductType == VER_NT_WORKSTATION) ps2 = "Professional";
               else if (oi.wSuiteMask & VER_SUITE_DATACENTER ) ps2 = "Datacenter Server";
               else if (oi.wSuiteMask & VER_SUITE_ENTERPRISE ) ps2 = "Advanced Server";
            break;

            case 0x501:
               ps1 = "XP";
               ps2 = 0 != (oi.wSuiteMask & VER_SUITE_PERSONAL) ? "Home Edition" : "Professional";
            break;

            case 0x502:
               if (::GetSystemMetrics(SM_SERVERR2) ) ps1 = "Server 2003 R2";
               else if (oi.wSuiteMask == VER_SUITE_STORAGE_SERVER) ps1 = "Storage Server 2003";
               else if (oi.wSuiteMask == VER_SUITE_WH_SERVER) ps1 = "Home Server";
               else if (oi.wProductType == VER_NT_WORKSTATION
                  && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
                  ps1 = "XP"; ps2 = "Professional x64 Edition";
               }
               else ps1 = "Server 2003";

               if (oi.wProductType != VER_NT_WORKSTATION) {
                  if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64) {
                     if (oi.wSuiteMask & VER_SUITE_DATACENTER) ps2 = "Datacenter Edition for Itanium-based Systems";
                     else if (oi.wSuiteMask & VER_SUITE_ENTERPRISE) ps2 = "Enterprise Edition for Itanium-based Systems";
                  }
                  else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) {
                     if (oi.wSuiteMask & VER_SUITE_DATACENTER) ps2 = "Datacenter x64 Edition";
                     else if (oi.wSuiteMask & VER_SUITE_ENTERPRISE) ps2 = "Enterprise x64 Edition";
                     else ps2 = "Standard x64 Edition";
                  }
                  else {
                     if (oi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) ps2 = "Compute Cluster Edition";
                     else if (oi.wSuiteMask & VER_SUITE_DATACENTER) ps2 = "Datacenter Edition";
                     else if (oi.wSuiteMask & VER_SUITE_ENTERPRISE) ps2 = "Enterprise Edition";
                     else if (oi.wSuiteMask & VER_SUITE_BLADE) ps2 = "Web Edition";
                     else ps2 = "Standard Edition";
                  }
               }
            break;

            case 0x600: case 0x601:
               if (oi.wProductType == VER_NT_WORKSTATION) ps1 = oi.dwMinorVersion == 0 ? "Vista" : "7";
               else ps1 =  oi.dwMinorVersion == 0 ? "Server 2008" : "Server 2008 R2";

               DWORD dwType = PRODUCT_UNDEFINED;
               if (NULL != (u.f=get_func("GetProductInfo"))) u.GetProductInfo(oi.dwMajorVersion,oi.dwMinorVersion,0,0,&dwType);
               switch( dwType ) {
                  case PRODUCT_ULTIMATE:          ps2 = "Ultimate Edition";       break;
                  case PRODUCT_HOME_PREMIUM:      ps2 = "Home Premium Edition";   break;
                  case PRODUCT_HOME_BASIC:        ps2 = "Home Basic Edition";     break;
                  case PRODUCT_ENTERPRISE:        ps2 = "Enterprise Edition";     break;
                  case PRODUCT_BUSINESS:          ps2 = "Business Edition";       break;
                  case PRODUCT_STARTER:           ps2 = "Starter Edition";        break;
                  case PRODUCT_CLUSTER_SERVER:    ps2 = "Cluster Server Edition"; break;
                  case PRODUCT_DATACENTER_SERVER: ps2 = "Datacenter Edition";     break;
                  case PRODUCT_DATACENTER_SERVER_CORE: ps2 = "Datacenter Edition (core installation)"; break;
                  case PRODUCT_ENTERPRISE_SERVER: ps2 = "Enterprise Edition";     break;
                  case PRODUCT_ENTERPRISE_SERVER_CORE: ps2 = "Enterprise Edition (core installation)"; break;
                  case PRODUCT_ENTERPRISE_SERVER_IA64: ps2 = "Enterprise Edition for Itanium-based Systems"; break;
                  case PRODUCT_SMALLBUSINESS_SERVER: ps2 = "Small Business Server"; break;
                  case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: ps2 = "Small Business Server Premium Edition"; break;
                  case PRODUCT_STANDARD_SERVER:   ps2 = "Standard Edition";       break;
                  case PRODUCT_STANDARD_SERVER_CORE: ps2 = "Standard Edition (core installation)"; break;
                  case PRODUCT_WEB_SERVER:        ps2 = "Web Server Edition";     break;
               }
            break;
         }
         ::lstrcatA(os, ps1); if (ps2) { ::lstrcatA(os, ", "); ::lstrcatA(os, ps2); }
      }
   }
   add_sp(os, oi.szCSDVersion);

   ::wsprintfA(release, "%u.%u.%u", oi.dwMajorVersion, oi.dwMinorVersion, oi.dwBuildNumber);
   ::wsprintfA(version, "%s %s", kernel, release);

   ps1 = NULL;
   processor[0] = '\0';
   if (oi.dwPlatformId < VER_PLATFORM_WIN32_NT) {
      ps1 = "x86";
      ::wsprintfA(processor, "i%u", si.dwProcessorType);
   }
   else {
      switch (si.wProcessorArchitecture) {
         case PROCESSOR_ARCHITECTURE_INTEL        : ps1 = "x86";     break;
         case PROCESSOR_ARCHITECTURE_AMD64        : ps1 = "amd64";   break;
         case PROCESSOR_ARCHITECTURE_MIPS         : ps1 = "mips";    break;
         case PROCESSOR_ARCHITECTURE_ALPHA        : ps1 = "alpha";   break;
         case PROCESSOR_ARCHITECTURE_PPC          : ps1 = "ppc";     break;
         case PROCESSOR_ARCHITECTURE_SHX          : ps1 = "shx";     break;
         case PROCESSOR_ARCHITECTURE_ARM          : ps1 = "arm";     break;
         case PROCESSOR_ARCHITECTURE_IA64         : ps1 = "ia64";    break;
         case PROCESSOR_ARCHITECTURE_ALPHA64      : ps1 = "alpha64"; break;
         case PROCESSOR_ARCHITECTURE_MSIL         : ps1 = "msil";    break;
         case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: ps1 = "ia32x64"; break;
      }
   }
   if (ps1) ::lstrcpyA(machine, ps1);
   if (!processor[0]) ::lstrcpyA(processor, machine);

   HKEY hk;
   LONG res = ::RegOpenKeyExA(
      HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,KEY_READ, &hk
   );
   if (res == ERROR_SUCCESS) {
      char id[100], nm[100], ve[32];
      DWORD dw, dt, MHz = 0; id[0] = nm[0] = ve[0] = '\0';

      dw = sizeof(id);
      ::RegQueryValueExA(hk, "Identifier", NULL, &dt, (LPBYTE)id, &dw);
      dw = sizeof(nm);
      ::RegQueryValueExA(hk, "ProcessorNameString", NULL, &dt, (LPBYTE)nm, &dw);
      dw = sizeof(ve);
      ::RegQueryValueExA(hk, "VendorIdentifier", NULL, &dt, (LPBYTE)ve, &dw);
      dw = sizeof(MHz);
      ::RegQueryValueExA(hk, "~MHz", NULL, &dt, (LPBYTE)&MHz, &dw);
      ::RegCloseKey(hk);
      if ( id[0] ) {
         bool x = (0 != (opts & e_X));
         char *po = processor, *ps = nm;
         while (*ps) { if (*ps != ' ' || ps[1] > ' ') *po++ = *ps; ++ps; }
         *po = '\0';
         if (!nm[0] || x) {
            if (nm[0]) { ::lstrcpyA(po, " - "); po += 3; }
            ::lstrcpyA(po, id); po += ::lstrlenA(po);
         }
         if (!nm[0] && MHz > 0) {
            if (MHz <= 950) po += ::wsprintfA(po, " @ %uMHz", MHz);
            else po += ::wsprintfA(po, " @ %u.%03uGHz", MHz/1000,MHz%1000);
         }
         if (!nm[0] || x) { ::wsprintfA(po, " - %s", ve); }
      }
   }

   if (0 != (opts & (e_a | e_X))) {
      out("System", kernel);
      out("Release", release);
      out("Version", version);
      out("Os", os);
      out("Host", host);
      out("Machine", machine);
      out("Cpu", processor);
      out("NumCpu", si.dwNumberOfProcessors);
      out("Memory", memory_size_mb(), "M");
      out("User", user);
   }
   else {
      ps1 = "";
      if (0 != (opts & e_s)) { out(ps1, kernel   ); ps1 = " "; }
      if (0 != (opts & e_r)) { out(ps1, release  ); ps1 = " "; }
      if (0 != (opts & e_v)) { out(ps1, version  ); ps1 = " "; }
      if (0 != (opts & e_n)) { out(ps1, host     ); ps1 = " "; }
      if (0 != (opts & e_m)) { out(ps1, machine  ); ps1 = " "; }
      if (0 != (opts & e_i)) { out(ps1, machine  ); ps1 = " "; }
      if (0 != (opts & e_p)) { out(ps1, processor); ps1 = " "; }
      if (0 != (opts & e_o)) { out(ps1, os       ); ps1 = " "; }
      if (0 != (opts & e_M)) { out(ps1, memory_size_mb()); ps1 = " "; }
      if (0 != (opts & e_c)) { out(ps1, si.dwNumberOfProcessors); ps1 = " "; }
      if (0 != (opts & e_u)) { out(ps1, user     ); ps1 = " "; }
      out("\r\n");
   }
   return 0;
}

//---------------------------------------------------------------------------------------

#ifdef _DEBUG
int _tmain( int argc, WCHAR **argv )
{
   (void)argc, argv;
   return Main();
}
#endif

//=======================================================================================
